using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class 帧更新控制器_核心 : MonoBehaviour
{

    private event UnityAction UpDateEvent;

    void Update()
    {
        if (UpDateEvent != null)
            UpDateEvent();

        延迟方法触发检测();
    }


    /// <summary>
    /// 给外部提供的 添加帧更新事件的函数
    /// </summary>
    /// <param name="方法"></param>
    public void 添加帧更新事件(UnityAction 方法)
    {
        UpDateEvent += 方法;
    }

    /// <summary>
    /// 提供给外部用于移除帧更新事件
    /// </summary>
    /// <param name="方法"></param>
    public void 移除帧更新事件(UnityAction 方法)
    {
        UpDateEvent -= 方法;
    }

    /// <summary>
    /// 清空事件列表
    /// </summary>
    public void 重置控制器() => UpDateEvent = null;

    public Coroutine 开启携程(IEnumerator routine) => StartCoroutine(routine);
    public void 停止携程(IEnumerator routine) => StopCoroutine(routine);
    public void 停止携程(Coroutine routine) => StopCoroutine(routine);


    private class 计时模块
    {
        public float 结束时间;
        public UnityAction fun;
        private float 延迟时间;
        public bool 循环;
        public 计时模块(float 延迟时间, UnityAction fun,bool 循环)
        {
            结束时间 = Time.time + 延迟时间;
            this.fun = fun;
            this.循环 = 循环;
            this.延迟时间 = 延迟时间;
        }
        public bool 执行结束()
        {
            if (Time.time >= 结束时间)
            {
                fun();
                if (循环)
                {
                    结束时间 = Time.time + 延迟时间;
                    return false;
                }
                else
                    return true;
            }
            else
                return false;
        }
    }

    List<计时模块> 延迟执行方法集合 = new List<计时模块>();
    private void 延迟方法触发检测()
    {
        //需要移除的列表
        int 数组长度 = 延迟执行方法集合.Count;
        for (int i = 0; i < 数组长度; i++)
        {
            if (延迟执行方法集合[i].执行结束())
            {
                延迟执行方法集合.RemoveAt(i);
                数组长度 = 延迟执行方法集合.Count;
                i--;
            }
        }
    }
    /// <summary>
    /// 延迟调用方法-只执行一次
    /// </summary>
    /// <param name="时间">循环的间隔</param>
    /// <param name="方法"></param>
    public void 延迟执行方法(float 时间, UnityAction 方法) => 延迟执行方法集合.Add(new 计时模块(时间, 方法, false));
    /// <summary>
    /// 每隔设置的时间将自动调用
    /// </summary>
    /// <param name="时间">循环的间隔</param>
    /// <param name="方法"></param>
    public void 周期性调用方法(float 时间,UnityAction 方法) => 延迟执行方法集合.Add(new 计时模块(时间, 方法, true));
    public void 移除延迟或周期性调用(UnityAction 方法)
    {
        int 索引 = -1;
        foreach (计时模块 item in 延迟执行方法集合)
        {
            if (item.fun == 方法)
            {
                索引 = 延迟执行方法集合.IndexOf(item);
                break;
            }
        }
        if (索引 != -1)
            延迟执行方法集合.RemoveAt(索引);
    }
}

/// <summary>
/// 可以提供给外部添加帧更新 的方法
/// 可以给外部提供携程的方法
/// </summary>
public class 帧更新控制器 : 单例_基础管理器<帧更新控制器>
{
    private 帧更新控制器_核心 实例;

    public 帧更新控制器()
    {
        GameObject obj = GameObject.Find("单例管理器");
        if (obj == null)
        {
            obj = new GameObject("单例管理器");
            GameObject.DontDestroyOnLoad(obj);
        }

        GameObject obj1 = new GameObject("帧更新控制器");
        实例 = obj1.AddComponent<帧更新控制器_核心>();
        obj1.transform.parent = obj.transform;
    }

    /// <summary>
    /// 给外部提供的 添加帧更新事件的函数
    /// </summary>
    /// <param name="方法"></param>
    public void 添加帧更新事件(UnityAction 方法) => 实例.添加帧更新事件(方法);

    /// <summary>
    /// 提供给外部用于移除帧更新事件
    /// </summary>
    /// <param name="方法"></param>
    public void 移除帧更新事件(UnityAction 方法) => 实例.移除帧更新事件(方法);


    /// <summary>
    /// 清空事件列表
    /// </summary>
    public void 重置控制器() => 实例.重置控制器();

    public Coroutine 开启携程(IEnumerator routine) => 实例.开启携程(routine);
    public void 停止携程(IEnumerator routine) => 实例.停止携程(routine);
    public void 停止携程(Coroutine routine) => 实例.停止携程(routine);

    /// <summary>
    /// 延迟调用方法-只执行一次
    /// </summary>
    /// <param name="时间">循环的间隔</param>
    /// <param name="方法"></param>
    public void 延迟执行方法(float 时间, UnityAction 方法) => 实例.延迟执行方法(时间, 方法);
    /// <summary>
    /// 每隔设置的时间将自动调用
    /// </summary>
    /// <param name="时间">循环的间隔</param>
    /// <param name="方法"></param>
    public void 周期性调用方法(float 时间, UnityAction 方法) => 实例.周期性调用方法(时间, 方法);
    /// <summary>
    /// 移除之前设置的周期性或延迟执行的方法
    /// </summary>
    /// <param name="方法"></param>
    public void 移除延迟或周期性调用(UnityAction 方法) => 实例.移除延迟或周期性调用(方法);
}
